/* global trackerCapture, angular */
import { processRegistration } from './processRegistration';

var trackerCapture = angular.module('trackerCapture');
trackerCapture.controller('RegistrationController', 
        function($rootScope,
                $q,
                $scope,
                $location,
                $timeout,
                $modal,
                $translate,
                $window,
                $parse,
                orderByFilter,
                AttributesFactory,
                DHIS2EventFactory,
                TEService,
                CustomFormService,
                EnrollmentService,
                NotificationService,
                CurrentSelection,
                MetaDataFactory,
                EventUtils,
                RegistrationService,
                DateUtils,
                TEIGridService,
                TEIService,
                TrackerRulesFactory,
                TrackerRulesExecutionService,
                TCStorageService,
                ModalService,
                SearchGroupService,
                AccessUtils,
                AuthorityService,
                SessionStorageService,
                AttributeUtils,
                TCOrgUnitService,
                ProgramFactory) {
    var prefilledTet = null;
    $scope.today = DateUtils.getToday();
    $scope.trackedEntityForm = null;
    $scope.customRegistrationForm = null;    
    $scope.selectedTei = {};       // Attribute values in the current form
    $scope.apiFormattedTei = {};   // API formatted version of $scope.selectedTei; see $scope.registerEntity(...) for details
    $scope.warningMessages = [];
    $scope.hiddenFields = [];    
    $scope.assignedFields = [];
    $scope.errorMessages = {};
    $scope.attributeUniquenessError = {};
    $scope.hiddenSections = [];
    $scope.mandatoryFields = [];
    $scope.currentEvent = null;
    $scope.completeEventOnRegistration = null;
    $scope.completeStageInfo = {description: $translate.instant("complete_stage_info")};
    $scope.prStDes = null;
    $scope.registrationAndDataEntry = false;
    $scope.model={autoGeneratedAttFailed : false, savingRegistration: false};
    $scope.helpTexts = {};
    $scope.registrationMode = 'REGISTRATION';
    var flag = {debug: true, verbose: $location.search().verbose ? true : false};
    $rootScope.ruleeffects = {};
    $scope.userAuthority = AuthorityService.getUserAuthorities(SessionStorageService.get('USER_PROFILE'));

    $scope.attributesById = CurrentSelection.getAttributesById();
    $scope.optionGroupsById = CurrentSelection.getOptionGroupsById();
    $scope.fileNames = CurrentSelection.getFileNames();
    $scope.currentFileNames = $scope.fileNames;

    //Placeholder till proper settings for time is implemented. Currently hard coded to 24h format.
    $scope.timeFormat = '24h';

    if(!$scope.attributesById){
        $scope.attributesById = [];
        AttributesFactory.getAll().then(function(atts){
            angular.forEach(atts, function(att){
                $scope.attributesById[att.id] = att;
            });
            
            CurrentSelection.setAttributesById($scope.attributesById);
        });
    }

    if(!$scope.optionGroupsById){
        MetaDataFactory.getAll('optionGroups').then(function(optionGroups){
            $scope.optionGroupsById = optionGroups.toHashMap('id', function(map,obj,key) { obj.optionsById = obj.options.toHashMap('id'); });
            CurrentSelection.setOptionGroupsById($scope.optionGroupsById);
        });
    }
    
    //get ouLevels
    $scope.ouLevels = CurrentSelection.getOuLevels();
    if(!$scope.ouLevels || $scope.ouLevels.length < 1){
        TCStorageService.currentStore.open().done(function(){
            TCStorageService.currentStore.getAll('ouLevels').done(function(response){
                var ouLevels = angular.isObject(response) ? orderByFilter(response, '-level').reverse() : [];
                CurrentSelection.setOuLevels(orderByFilter(ouLevels, '-level').reverse());
            });
        });
    }
    
    $scope.optionSets = CurrentSelection.getOptionSets();        
    if(!$scope.optionSets){
        $scope.optionSets = [];
        MetaDataFactory.getAll('optionSets').then(function(optionSets){
            angular.forEach(optionSets, function(optionSet){                        
                $scope.optionSets[optionSet.id] = optionSet;
            });
            CurrentSelection.setOptionSets($scope.optionSets);
        });
    }
    
    
    $scope.isDisabled = function(attribute) {
        return attribute.generated || $scope.assignedFields[attribute.id] || $scope.editingDisabled;
    };

    $scope.selectedEnrollment = {
        enrollmentDate: $scope.today,
        incidentDate: $scope.today,
        orgUnit: $scope.selectedOrgUnit.id,
        orgUnitName: $scope.selectedOrgUnit ? $scope.selectedOrgUnit.displayName : ""
    };

    $scope.trackedEntityTypes = {available: []};
    var trackedEntityTypesById = {};

    var loadTrackedEntityTypes = function(){
        if(!$scope.trackedEntityTypes || $scope.trackedEntityTypes.available.length === 0){
            return TEService.getAll().then(function (entities) {
                var currentTet = prefilledTet || ($scope.selectedTei && $scope.selectedTei.trackedEntityType);
                angular.forEach(entities, function(entity){
                    trackedEntityTypesById[entity.id] = entity;
                });
                $scope.trackedEntityTypes.available = AccessUtils.toWritable(entities);
                $scope.trackedEntityTypes.writable = $scope.trackedEntityTypes.available.filter(function(t) { return t.access && t.access.data.write });
                setSelectedTrackedEntityType(currentTet);
            });
        }else{
            var def = $q.defer();
            def.resolve();
            setSelectedTrackedEntityType();
            return def.promise;
        }

    }

    var setSelectedTrackedEntityType = function(currentTet){
        if($scope.selectedProgram){
            $scope.trackedEntityTypes.selected = trackedEntityTypesById[$scope.selectedProgram.trackedEntityType.id];
        }else if(currentTet){
            $scope.trackedEntityTypes.selected = $scope.trackedEntityTypes.writable.find(function(t) { return t.id === currentTet });
            $scope.setTrackedEntityType();
        } else if($location.search().tracked_entity_type) {
            $scope.trackedEntityTypes.selected = $scope.trackedEntityTypes.writable.find(function(t) { return t.id === $location.search().tracked_entity_type });
            $scope.setTrackedEntityType();
        }
    }


    var getProgramRules = function () {
        $scope.trackedEntityForm = null;
        $scope.customRegistrationForm = null;
        $scope.allProgramRules = {
            constants: [],
            programIndicators: {},
            programVariables: [],
            programRules: []
        };
        if (angular.isObject($scope.selectedProgram) && $scope.selectedProgram.id) {
            return TrackerRulesFactory.getRules($scope.selectedProgram.id).then(function (rules) {
                $scope.allProgramRules = rules;
            });
        }
    };
    $scope.hasTeiWrite = function(){
        return $scope.trackedEntityTypes && $scope.trackedEntityTypes.selected && $scope.trackedEntityTypes.selected.access.data.write;
    }
    var setSearchConfig = function(){
        var promise = null;
        $scope.programSearchScope = false;
        if($scope.selectedProgram){
            $scope.programSearchScope = true;
            promise = SearchGroupService.getSearchConfigForProgram($scope.selectedProgram);
        }else if($scope.trackedEntityTypes && $scope.trackedEntityTypes.selected){
            promise = SearchGroupService.getSearchConfigForTrackedEntityType($scope.trackedEntityTypes.selected);
        }
        if(promise){
            promise.then(function(searchConfig){
                $scope.searchConfig = searchConfig;
                SearchGroupService.getSearchConfigForTrackedEntityType($scope.trackedEntityTypes.selected).then(function(tetSearchConfig){
                    $scope.tetSearchConfig = tetSearchConfig;
                });
                if($scope.searchConfig){
                    for(var key in $scope.selectedTei){
                        if($scope.attributesById[key]){
                            var groups = $scope.searchConfig.searchGroupsByAttributeId[key];
                            if(groups){
                                if(groups.default){
                                    groups.default[key] = $scope.selectedTei[key];
                                }
                                if(groups.unique){
                                    groups.unique[key] = $scope.selectedTei[key];
                                }
                            }
                        }
                    }
                }
            });
        }
        return promise;
    }
    //watch for selection of program
    $scope.$watch('selectedProgram', function (newValue, oldValue) {
        if (newValue !== oldValue) {
            getProgramRules();

            if ($scope.registrationMode === 'REGISTRATION') {
                $scope.getAttributes($scope.registrationMode, false);
            }
        }
        loadTrackedEntityTypes().then(function(){
            setSearchConfig();
        });
        

        $scope.model.minEnrollmentDate = "";
        $scope.model.maxEnrollmentDate =  ($scope.selectedProgram && $scope.selectedProgram.selectEnrollmentDatesInFuture) ? '' : "0";
        if ($scope.selectedOrgUnit.reportDateRange) {
            if ($scope.selectedOrgUnit.reportDateRange.minDate) {
                $scope.model.minEnrollmentDate = DateUtils.formatFromApiToUserCalendar($scope.selectedOrgUnit.reportDateRange.minDate);
                $scope.model.minEnrollmentDate = DateUtils.formatFromApiToUser($scope.model.minEnrollmentDate);
            }
            if ($scope.selectedOrgUnit.reportDateRange.maxDate) {
                $scope.model.maxEnrollmentDate = $scope.selectedOrgUnit.reportDateRange.maxDate;
            }
        }
    });



    //listen to modes of registration
    $scope.$on('registrationWidget', function (event, args) {
        $scope.selectedTei = {};
        $scope.apiFormattedTei = {};
        $scope.registrationMode = args.registrationMode;
        $scope.orgUnitNames = CurrentSelection.getOrgUnitNames();

        if ($scope.registrationMode !== 'REGISTRATION') {
            $scope.selectedTei = args.selectedTei || {};
            $scope.apiFormattedTei = angular.copy(args.selectedTei);

            
        }

        if($scope.registrationMode === 'REGISTRATION'){
            if($scope.registrationPrefill && !$scope.registrationPrefill.finished){
                if(!$scope.selectedProgram){
                    prefilledTet = $scope.registrationPrefill["tet"];
                    if($scope.trackedEntityTypes.writable){
                        $scope.trackedEntityTypes.selected = $scope.trackedEntityTypes.writable.find(function(t) { return t.id === prefilledTet });
                    }
                }
                for(var key in $scope.registrationPrefill){
                    if($scope.attributesById[key]){
                        $scope.apiFormattedTei[key] = $scope.selectedTei[key] = $scope.registrationPrefill[key];
                        if($scope.searchConfig){
                            var groups = $scope.searchConfig.searchGroupsByAttributeId[key];
                            if(groups){
                                if(groups.default){
                                    groups.default[key] = $scope.registrationPrefill[key];
                                }
                                if(groups.unique){
                                    groups.unique[key] = $scope.registrationPrefill[key];
                                }
                            }
                        }
                    }
                }
                $scope.registrationPrefill.finished = true;
            }
            CurrentSelection.set({
                te: $scope.trackedEntityTypes.selected,
                pr: $scope.selectedProgram,
                orgUnit: $scope.selectedOrgUnit
            });

        }

        $scope.teiOriginal = angular.copy($scope.apiFormattedTei);
        $scope.teiPreviousValues = angular.copy($scope.apiFormattedTei);

        if ($scope.registrationMode === 'PROFILE') {
            $scope.selectedEnrollment = args.enrollment ? args.enrollment : {};
        }

        $scope.getAttributes($scope.registrationMode, args.generateAttributes);

        if ($scope.selectedProgram && $scope.selectedProgram.id) {
            getProgramRules().then( function (rules) {
                $scope.executeRules();
            });
        }
    });

    $scope.getAttributes = function (_mode, generateAttributes) {
        var mode = _mode ? _mode : 'ENROLLMENT';
        $scope.customRegistrationFormExists = false;
        $scope.customDataEntryForm = null;
        $scope.schedulingEnabled = true;

        if( $scope.selectedProgram && $scope.selectedProgram.captureCoordinates && angular.isObject($scope.selectedEnrollment) ){                
            $scope.selectedEnrollment.coordinate = $scope.selectedEnrollment.coordinate ? $scope.selectedEnrollment.coordinate : {};
        }

        var trackedEntityType = $scope.trackedEntityTypes.selected;

        if($scope.selectedProgram){
            if (!trackedEntityType) {
                trackedEntityType = $scope.selectedProgram.trackedEntityType;
            }
            AttributesFactory.getByProgram($scope.selectedProgram).then(function (atts) {
                $scope.attributes = TEIGridService.generateGridColumns(atts, null, false).columns;
                if (generateAttributes) {
                    fetchGeneratedAttributes();
                }
                if ($scope.selectedProgram && $scope.selectedProgram.id) {
                    if ($scope.selectedProgram.dataEntryForm && $scope.selectedProgram.dataEntryForm.htmlCode) {
                        $scope.customRegistrationFormExists = true;
                        $scope.trackedEntityForm = $scope.selectedProgram.dataEntryForm;
                        $scope.trackedEntityForm.attributes = $scope.attributes;
                        $scope.trackedEntityForm.selectIncidentDatesInFuture = $scope.selectedProgram.selectIncidentDatesInFuture;
                        $scope.trackedEntityForm.selectEnrollmentDatesInFuture = $scope.selectedProgram.selectEnrollmentDatesInFuture;
                        $scope.trackedEntityForm.displayIncidentDate = $scope.selectedProgram.displayIncidentDate;
                        $scope.customRegistrationForm = CustomFormService.getForTrackedEntity($scope.trackedEntityForm, mode);
                    }
    
                    if ($scope.selectedProgram.programStages 
                        && $scope.selectedProgram.programStages[0] 
                        && $scope.selectedProgram.useFirstStageDuringRegistration
                        && $scope.selectedProgram.programStages[0].access.data.write
                        && $scope.registrationMode === 'REGISTRATION') {
                        $scope.currentEvent = {};
                        $scope.registrationAndDataEntry = true;
                        $scope.prStDes = [];
                        $scope.currentStage = $scope.selectedProgram.programStages[0];
                        $scope.currentEvent.event = 'SINGLE_EVENT';
                        $scope.currentEvent.providedElsewhere = {};
                        $scope.currentEvent.orgUnit = $scope.selectedOrgUnit.id;
                        $scope.currentEvent.program = $scope.selectedProgram.id;
                        $scope.currentEvent.programStage = $scope.currentStage.id;
                        $scope.currentEvent.enrollmentStatus = $scope.currentEvent.status = 'ACTIVE';
                        $scope.currentEvent.executionDateLabel = $scope.currentStage.executionDateLabel;
                        $rootScope.ruleeffects[$scope.currentEvent.event] = {};
                        $scope.selectedEnrollment.status = 'ACTIVE';
    
                        if( $scope.currentStage.captureCoordinates ){                            
                            $scope.currentEvent.coordinate = {};
                        }
    
                        angular.forEach($scope.currentStage.programStageDataElements, function (prStDe) {                            
                            $scope.prStDes[prStDe.dataElement.id] = prStDe;
                            if (prStDe.allowProvidedElsewhere) {
                                $scope.allowProvidedElsewhereExists[$scope.currentStage.id] = true;
                            }
                        });
                        $scope.currentEventOriginal = angular.copy($scope.currentEvent);
                        $scope.customDataEntryForm = CustomFormService.getForProgramStage($scope.currentStage, $scope.prStDes);
                    }
                }
            });
        }

        if(trackedEntityType){
            AttributesFactory.getByTrackedEntityType(trackedEntityType).then(function (atts) {
                $scope.teTypeAttributesById = {};
                angular.forEach(atts,function(att){
                    $scope.teTypeAttributesById[att.id] = att;
                });
                
                if(!$scope.selectedProgram){
                    $scope.attributes = TEIGridService.generateGridColumns(atts, null, false).columns;
                    if (generateAttributes) {
                        fetchGeneratedAttributes();
                    }
                }
            });
        }


    };

    var fetchGeneratedAttributes = function() {
        angular.forEach($scope.attributes, function(att) {
            $scope.fetchGeneratedAttribute(att);
        });
    };

    $scope.fetchGeneratedAttribute = function(att) {
        if (att.generated && !$scope.selectedTei[att.id]) {
            AttributeUtils.generateUniqueValue(att.id, $scope.selectedTei, $scope.selectedProgram, $scope.selectedOrgUnit).then(function (data) {
                if (data && data.status === "ERROR") {
                    NotificationService.showNotifcationDialog($translate.instant("error"), data.message);
                    $scope.model.autoGeneratedAttFailed = true;
                } else {
                    if (att.valueType === "NUMBER") {
                        $scope.selectedTei[att.id] = Number(data);
                    } else {
                        $scope.selectedTei[att.id] = data;
                    }
                    $scope.model.autoGeneratedAttFailed = false;
                }
            });
        }
    }

    $scope.uninitializedGeneratedAttribute = function(att) {
        return att.generated && !$scope.selectedTei[att.id];
    }

    var goToDashboard = function (destination, teiId) {
        //reset form
        $scope.selectedTei = {};
        $scope.selectedEnrollment = {
            enrollmentDate: $scope.today,
            incidentDate: $scope.today,
            orgUnit: $scope.selectedOrgUnit.id,
            orgUnitName: $scope.selectedOrgUnit.displayName
        };
        $scope.outerForm.submitted = false;
        $scope.outerForm.$setPristine();

        if (destination === 'DASHBOARD') {
            $location.path('/dashboard').search({
                tei: teiId,
                program: $scope.selectedProgram ? $scope.selectedProgram.id : null,
                ou:$scope.selectedOrgUnit.id
            });
        }
        else if (destination === 'SELF') {
            //notify user
            var headerText =  $translate.instant("success");
            var bodyText =  $translate.instant("registration_complete");
            NotificationService.showNotifcationDialog(headerText, bodyText);
            $scope.selectedTei = {};
            $scope.apiFormattedTei = {};
            $scope.currentEvent = {};
            $timeout(function() {
                $rootScope.$broadcast('registrationWidget', {registrationMode: 'REGISTRATION'});
            });
        }
    };

    var updateCurrentSelection = function() {
        var selections = CurrentSelection.get();
        CurrentSelection.set({
            tei: $scope.selectedTei,
            te: selections.te,
            prs: selections.prs,
            pr: $scope.selectedProgram,
            prNames: selections.prNames,
            prStNames: selections.prStNames,
            enrollments: $scope.selectedTei.enrollments,
            selectedEnrollment: $scope.selectedEnrollment,
            optionSets: selections.optionSets,
            orgUnit: selections.orgUnit
        });
    }

    var reloadProfileWidget = function () {
        updateCurrentSelection();
        $timeout(function () {
            $rootScope.$broadcast('profileWidget', {});
        }, 200);
    };

    var notifyRegistrtaionCompletion = function (destination, teiId) {
        if ($scope.registrationMode === 'ENROLLMENT') {
            broadcastTeiEnrolled();
        }
        else {
            goToDashboard(destination ? destination : 'DASHBOARD', teiId);
        }
    };

    $scope.$on('changeOrgUnit', function (event, args) {
        $scope.apiFormattedTei.orgUnit = args.orgUnit;
    });

    var performRegistration = function (destination) {
        if (destination === "DASHBOARD" || destination === "SELF" || destination === "ENROLLMENT") {
           $scope.model.savingRegistration = true;
        }

        //Temp fix for not being able to save images with attribute.value = "" or null.
        var tempAttributes = [];
        angular.forEach($scope.apiFormattedTei.attributes, function (attribute) {
            if(attribute.value !== '' && attribute.value != null ) {
                tempAttributes.push(attribute);
            }
        });

        $scope.apiFormattedTei.attributes = tempAttributes;

        $scope.returnUrl;
        if ( $location.search().returnUrl ) {
            $scope.returnUrl = $location.search().returnUrl;
        }

        RegistrationService.registerOrUpdate($scope.apiFormattedTei, $scope.optionSets, $scope.attributesById, $scope.selectedEnrollment.program).then(function (regResponse) {
            var reg = regResponse.response.responseType ==='ImportSummaries' ? regResponse.response.importSummaries[0] : regResponse.response.responseType === 'ImportSummary' ? regResponse.response : {};
            if (reg.status === 'SUCCESS') {
                $scope.apiFormattedTei.trackedEntityInstance = reg.reference;
                
                if ($scope.registrationMode === 'PROFILE') {
                    reloadProfileWidget();
                    $rootScope.$broadcast('teiupdated', {});
                    $scope.model.savingRegistration = false;
                    if(destination === 'newOrgUnit'){
                        $scope.selectedEnrollment.orgUnit = $scope.apiFormattedTei.orgUnit;
                        EnrollmentService.update($scope.selectedEnrollment);
                        selection.load();
                        if($scope.returnUrl) {
                            $location.path(atob(returnUrl));
                        } else {
                            $location.path('/').search({program: $scope.selectedProgram.id}); 
                        }
                    }
                }
                else {
                    updateCurrentSelection();
                    if ($scope.selectedProgram) {

                        //enroll TEI
                        var enrollment = {};
                        enrollment.trackedEntityInstance = $scope.apiFormattedTei.trackedEntityInstance;
                        enrollment.program = $scope.selectedProgram.id;
                        enrollment.status = 'ACTIVE';
                        enrollment.orgUnit = $scope.selectedOrgUnit.id;
                        enrollment.enrollmentDate = $scope.selectedEnrollment.enrollmentDate;
                        enrollment.incidentDate = $scope.selectedEnrollment.incidentDate === '' ? $scope.selectedEnrollment.enrollmentDate : $scope.selectedEnrollment.incidentDate;

                        if( $scope.selectedEnrollment.geometry ){
                            enrollment.geometry = $scope.selectedEnrollment.geometry;
                        }

                        EnrollmentService.enroll(enrollment).then(function (enrollmentResponse) {
                            if(enrollmentResponse) {
                                var en = enrollmentResponse.response;
                                if (en.status === 'SUCCESS') {
                                    TEIService.flushCachedTei();
                                    if($scope.registrationMode !== 'ENROLLMENT') {
                                        $scope.model.savingRegistration = false;
                                    }
                                    enrollment.enrollment = en.importSummaries[0].reference;
                                    var availableEvent = $scope.currentEvent && $scope.currentEvent.event ? $scope.currentEvent : null;
                                    var dhis2Events = EventUtils.autoGenerateEvents($scope.apiFormattedTei.trackedEntityInstance, $scope.selectedProgram, $scope.selectedOrgUnit, enrollment, availableEvent);
                                    if (dhis2Events.events.length > 0) {
                                        DHIS2EventFactory.create(dhis2Events).then(function () {
                                            notifyRegistrtaionCompletion(destination, $scope.apiFormattedTei.trackedEntityInstance);
                                        });
                                    } else {
                                        notifyRegistrtaionCompletion(destination, $scope.apiFormattedTei.trackedEntityInstance);
                                    }
                                }
                                else {
                                    //enrollment has failed
                                    $scope.model.savingRegistration = false;
                                    NotificationService.showNotifcationDialog($translate.instant("enrollment_error"), enrollmentResponse.message);
                                    return;
                                }
                            }
                        });
                    }
                    else {
                        notifyRegistrtaionCompletion(destination, $scope.apiFormattedTei.trackedEntityInstance);
                        $scope.model.savingRegistration = false;
                    }
                }
            }
            else {//update/registration has failed
                var headerText = $scope.apiFormattedTei && $scope.apiFormattedTei.trackedEntityInstance ? $translate.instant('update_error') :
                                 $translate.instant('registration_error');
                var bodyText = regResponse.message;
                NotificationService.showNotifcationDialog(headerText, bodyText);
                $scope.model.savingRegistration = false;
                return;
            }
        });

    };

    function broadcastTeiEnrolled() {
        $rootScope.$broadcast('teienrolled', {});
    }

    /* 
    We decided to temporarily(?) remove the ongoing checks for duplicates and run them only when the form is submitted.
    This was due to the performance problems in Bangladesh. This is the event handler for the submit click.
    */
    $scope.processRegistration = function (destination) {
        $scope.validatingRegistration = true;
        //check for form validity
        $scope.outerForm.submitted = true;
        if ($scope.outerForm.$invalid) {
            $scope.validatingRegistration = false;
            return false;
        }

        if ($scope.model.autoGeneratedAttFailed) {
            NotificationService.showNotifcationDialog($translate.instant("registration_error"), $translate.instant("auto_generate_failed"));
            $scope.validatingRegistration = false;
            return false;
        }

        if ($scope.registrationAndDataEntry) {
            $scope.outerDataEntryForm.submitted = true;
            if ($scope.outerDataEntryForm.$invalid) {
                $scope.validatingRegistration = false;
                return false;
            }
        }

        processRegistration(destination, {
            SearchGroupService,
            tei: $scope.selectedTei,
            searchGroups: $scope.searchConfig.searchGroups,
            useProgramSearchScope: $scope.programSearchScope,
            tetSearchConfig: $scope.tetSearchConfig,
            attributesById: $scope.attributesById,
            program: $scope.selectedProgram,
            trackedEntityType: $scope.trackedEntityTypes.selected,
            orgUnit: $scope.selectedOrgUnit,
            showMatchesModal: $scope.showMatchesModal,
            showDuplicateModal,
            registerEntity: $scope.registerEntity,
            $q,
            onOpenModal: () => {
                $scope.validatingRegistration = false;
            }
        })
        .then(result => {
            if(result && result.duplicateUniqueAttributeId) {
                $scope.attributeUniquenessError[result.duplicateUniqueAttributeId] = true;
            }
            $scope.validatingRegistration = false;
        })
        .catch(error => {
            console.log(error);
            $scope.validatingRegistration = false;
        });
    }

    $scope.registerEntity = function (destination, isFormPrechecked) {
        if (!isFormPrechecked) {
            //check for form validity
            $scope.outerForm.submitted = true;
            if ($scope.outerForm.$invalid) {
                return false;
            }

            if ($scope.model.autoGeneratedAttFailed) {
                NotificationService.showNotifcationDialog($translate.instant("registration_error"), $translate.instant("auto_generate_failed"));
                return false;
            }

            if ($scope.registrationAndDataEntry) {
                $scope.outerDataEntryForm.submitted = true;
                if ($scope.outerDataEntryForm.$invalid) {
                    return false;
                }
            }
        }

        //form is valid, continue the registration
        //get selected entity
        if (!$scope.selectedTei.trackedEntityInstance) {
            $scope.selectedTei.trackedEntityType = $scope.apiFormattedTei.trackedEntityType = $scope.selectedProgram && $scope.selectedProgram.trackedEntityType && $scope.selectedProgram.trackedEntityType.id ? $scope.selectedProgram.trackedEntityType.id : $scope.trackedEntityTypes.selected.id;
            $scope.selectedTei.orgUnit = $scope.apiFormattedTei.orgUnit = $scope.selectedOrgUnit.id;
            $scope.selectedTei.attributes = $scope.apiFormattedTei.attributes = [];
        }
        $scope.apiFormattedTei.featureType = $scope.selectedTei.featureType;
        $scope.apiFormattedTei.geometry = $scope.selectedTei.geometry;
        //get tei attributes and their values
        //but there could be a case where attributes are non-mandatory and
        //registration form comes empty, in this case enforce at least one value
        var result = RegistrationService.processForm($scope.apiFormattedTei, $scope.selectedTei, $scope.teiOriginal, $scope.attributesById);
        $scope.formEmpty = result.formEmpty;
        $scope.apiFormattedTei = result.tei;

        if ($scope.formEmpty) {//registration form is empty
            NotificationService.showNotifcationDialog($translate.instant("error"), $translate.instant("form_is_empty_fill_at_least_one"));
            return;
        }
        if(!destination && $scope.apiFormattedTei) {
            TEIService.getRelationships($scope.apiFormattedTei.trackedEntityInstance).then(function(result) {
                $scope.apiFormattedTei.relationships = result;
                performRegistration(destination);
            });
        } else {
            performRegistration(destination);
        }
    };

    $scope.executeRules = function () {
        //repopulate attributes with updated values
        $scope.selectedTei.attributes = [];
        angular.forEach($scope.attributes, function (metaAttribute) {
            var newAttributeInArray = {
                attribute: metaAttribute.id,
                code: metaAttribute.code,
                displayName: metaAttribute.displayName,
                type: metaAttribute.valueType,
                value: $scope.selectedTei[metaAttribute.id]
            };

            $scope.selectedTei.attributes.push(newAttributeInArray);
        });

        if ($scope.selectedProgram && $scope.selectedProgram.id) {
            var eventExists = $scope.currentEvent && $scope.currentEvent.event;
            var enrollment = $scope.selectedEnrollment && $scope.selectedEnrollment.orgUnit ? $scope.selectedEnrollment : null;
            var evs = null;
            if( eventExists ){
                evs = {all: [], byStage: {}};
                evs.all = [$scope.currentEvent];
                evs.byStage[$scope.currentStage.id] = [$scope.currentEvent];
            }
            if (eventExists || enrollment) {
                TrackerRulesExecutionService.executeRules(
                $scope.allProgramRules, 
                eventExists ? $scope.currentEvent : 'registration', 
                evs,
                $scope.prStDes, 
                $scope.attributesById,
                $scope.selectedTei, 
                enrollment,
                $scope.optionSets, 
                flag);
            }
        }
    };

    //check if field is hidden
    $scope.isHidden = function (id) {
        
        if($scope.currentEvent && $scope.hiddenFields[$scope.currentEvent.event] && $scope.hiddenFields[$scope.currentEvent.event][id]){
            return $scope.hiddenFields[$scope.currentEvent.event][id];
        }
        return false;
    };

    $scope.teiValueUpdated = function (tei, field) {
        if ($scope.teiPreviousValues[field] !== tei[field] && $scope.attributeUniquenessError[field]) {
            $scope.attributeUniquenessError[field] = false;
        }
        
        $scope.teiPreviousValues[field] = tei[field];
        return $scope.executeRules();
    };

    var getMatchingTeisCount = function(tei, field){
        var promises = [];
        if($scope.registrationMode === 'REGISTRATION') {
            var searchGroups = $scope.searchConfig.searchGroupsByAttributeId[field];
            if(searchGroups){
                if(searchGroups.default){
                    searchGroups.default[field] = tei[field];
                    promises.push(getMatchingTeisCountBySearchGroup(searchGroups.default, field));
                } 
                if(searchGroups.unique){
                    searchGroups.unique[field] = tei[field];
                    promises.push(getMatchingTeisCountBySearchGroup(searchGroups.unique, field));
                }
            }else{
                var def = $q.defer();
                def.resolve();
                promises.push(def.promise);
            }
        }

        return $q.all(promises);
    }

    var getMatchingTeisCountBySearchGroup = function(searchGroup,field){
        var promise;
        if($scope.programSearchScope){
            var tetSearchGroup = SearchGroupService.findValidTetSearchGroup(searchGroup, $scope.tetSearchConfig, $scope.attributesById);
            promise = SearchGroupService.programScopeSearchCount(searchGroup,tetSearchGroup, $scope.selectedProgram,$scope.trackedEntityTypes.selected, $scope.selectedOrgUnit, true).then(function(count){
                if(searchGroup.uniqueGroup && count > 0){
                    return SearchGroupService.programScopeSearch(searchGroup,tetSearchGroup, $scope.selectedProgram,$scope.trackedEntityTypes.selected, $scope.selectedOrgUnit).then(function(res){
                        return showDuplicateModal(res.data, field);
                    });
                }
                $scope.matchingTeisCount = count;
                $scope.matchingTeisSearchGroup = searchGroup;
                
            });
        }else{
            promise = SearchGroupService.tetScopeSearchCount(searchGroup, $scope.trackedEntityTypes.selected, $scope.selectedOrgUnit).then(function(count){
                if(searchGroup.uniqueGroup && count > 0){
                    return SearchGroupService.tetScopeSearch(searchGroup, $scope.trackedEntityTypes.selected, $scope.selectedOrgUnit).then(function(res){
                        return showDuplicateModal(res.data, field);
                    });
                }
                $scope.matchingTeisCount = count;
                $scope.matchingTeisSearchGroup = searchGroup;
            });
        }
    }

    var searchForExistingTeisBySearchGroup = function(searchGroup,field){
        var promise;
        if($scope.programSearchScope){
            var tetSearchGroup = SearchGroupService.findValidTetSearchGroup(searchGroup, $scope.tetSearchConfig, $scope.attributesById);
            promise = SearchGroupService.programScopeSearch(searchGroup,tetSearchGroup, $scope.selectedProgram,$scope.trackedEntityTypes.selected, $scope.selectedOrgUnit);
        }else{
            promise = SearchGroupService.tetScopeSearch(searchGroup,$scope.trackedEntityTypes.selected, $scope.selectedOrgUnit);

        }

        return promise.then(function(res){
            if(res.status === "NOMATCH"){
                $scope.matchingTeis = [];
                return;
            }
            if(res.status === "MATCHES" && $scope.registrationMode === "REGISTRATION"){
                $scope.matchingTeis = res.data;
                $scope.matchingTeisSearchGroup = searchGroup;
            }
            if(res.status === "UNIQUE"){
                return showDuplicateModal(res.data, field);
            }
        });

    }

    $scope.saveDataValueForRadio = function(field, context, value){
        var promise = null;
        if(field.dataElement) {
            //The saveDataValueForRadio was called from the dataentry template. Update dataelement og current event:
            context[field.dataElement.id] = value;
            var def = $q.defer();
            def.resolve();
            promise = def.promise;
        }
        else {
            context[field.id] = value;
            promise = getMatchingTeisCount(context,field).then(function(){
                $scope.teiPreviousValues[field.id] = context[field.id];
            });
        }
        promise.then(function()
        {
            return $scope.executeRules();
        }, function(){
            return;
        });
    }

    $scope.setCompleteStage = function (value) {
        if(value === "true") {
            $scope.currentEvent.status = "COMPLETED";
        } else {
            $scope.currentEvent.status = "ACTIVE";
        }
    }

    //listen for rule effect changes
    $scope.$on('ruleeffectsupdated', function (event, args) {
        if (args.event === "registration" || args.event === 'SINGLE_EVENT') {
            $scope.warningMessages = [];
            $scope.hiddenFields = [];
            $scope.assignedFields = [];
            $scope.errorMessages = {};
            $scope.hiddenSections = [];

            var effectResult = TrackerRulesExecutionService.processRuleEffectAttribute(args.event, $scope.selectedTei, $scope.apiFormattedTei, $scope.currentEvent, {}, $scope.currentEvent, $scope.attributesById, $scope.prStDes,$scope.optionSets, $scope.optionGroupsById);
            $scope.selectedTei = effectResult.selectedTei;
            $scope.currentEvent = effectResult.currentEvent;
            $scope.hiddenFields = effectResult.hiddenFields;
            $scope.hiddenSections = effectResult.hiddenSections;
            $scope.assignedFields = effectResult.assignedFields;
            $scope.warningMessages = effectResult.warningMessages;
            $scope.mandatoryFields = effectResult.mandatoryFields;
            $scope.optionVisibility = effectResult.optionVisibility;
            if($scope.assignedFields){
                var searchedGroups = {};
                angular.forEach($scope.assignedFields, function(field){
                    var groups = $scope.searchConfig.searchGroupsByAttributeId[field];
                    if(groups){
                        if(groups.default && searchedGroups[groups.default.id]){
                            searchForExistingTeisBySearchGroup(groups.default);
                            searchedGroups[groups.default.id] = true;  
                        }
                        if(groups.unique && searchedGroups[groups.unique.id]){
                            searchForExistingTeisBySearchGroup(groups.unique);
                            searchedGroups[groups.unique.id] = true;  
                        }
                    }    
                });
            }
        }
    });

    $scope.interacted = function (field) {
        var status = false;
        if (field) {
            status = $scope.outerForm.submitted || field.$dirty;
        }
        return status;
    };

    var allPrograms = null;
    var getAllPrograms = function () {
        var def = $q.defer();
        if(allPrograms) {
            def.resolve(allPrograms);
        }else{
            ProgramFactory.getAll().then(function(result) {
                allPrograms = result.programs;
                def.resolve(allPrograms);
            });
        }

        return def.promise;

    }


    $scope.getTrackerAssociate = function (selectedAttribute, existingAssociateUid) {
        return getAllPrograms().then(function(allProgramsResult){
            var modalInstance = $modal.open({
                templateUrl: 'components/teiadd/tei-add.html',
                controller: 'TEIAddController',
                windowClass: 'modal-full-window',
                resolve: {
                    relationshipTypes: function () {
                        return $scope.relationshipTypes;
                    },
                    addingRelationship: function () {
                        return false;
                    },
                    selections: function () {
                        return CurrentSelection.get();
                    },
                    selectedTei: function () {
                        return $scope.selectedTei;
                    },
                    selectedAttribute: function () {
                        return selectedAttribute;
                    },
                    existingAssociateUid: function () {
                        return existingAssociateUid;
                    },
                    selectedProgram: function () {
                        return $scope.selectedProgram;
                    },
                    relatedProgramRelationship: function () {
                        return $scope.relatedProgramRelationship;
                    },
                    allPrograms: function () {
                        return allProgramsResult;
                    },
                }
            });
            return modalInstance.result.then(function (res) {
                if (res && res.id) {
                    //Send object with tei id and program id
                    $scope.selectedTei[selectedAttribute.id] = res.id;
                }
                return res;
            });

        });
    };

    $scope.cancelRegistrationWarning = function (cancelFunction, inDashboard) {
        var result = RegistrationService.processForm($scope.apiFormattedTei, $scope.selectedTei, $scope.teiOriginal, $scope.attributesById);
        var prStDe;
        if (!result.formChanged) {
            if ($scope.currentStage &&  $scope.currentStage.programStageDataElements) {
                for (var index = 0; index < $scope.currentStage.programStageDataElements.length; index++) {
                    prStDe = $scope.currentStage.programStageDataElements[index];
                    if ($scope.currentEvent[prStDe.dataElement.id]) {
                        result.formChanged = true;
                        break;
                    }
                }
            }
        }
        if (result.formChanged) {
            var modalOptions = {
                closeButtonText: 'no',
                actionButtonText: 'yes',
                headerText: 'cancel',
                //Depending on if you are editing in dashboard or registering a new TEI you get a different cancel message.
                bodyText: inDashboard ? 'are_you_sure_to_cancel_editing' : 'are_you_sure_to_cancel_registration'
            };

            ModalService.showModal({}, modalOptions).then(function () {
                $scope.outerForm.$setPristine();
                cancelFunction();
            });
        }
        else {
            $scope.outerForm.$setPristine();
            cancelFunction();
        }
    };



    var getMatches = function(searchGroup){
        var promise;
        if($scope.programSearchScope){
            var tetSearchGroup = SearchGroupService.findValidTetSearchGroup(searchGroup, $scope.tetSearchConfig, $scope.attributesById);
            promise = SearchGroupService.programScopeSearch(searchGroup,tetSearchGroup, $scope.selectedProgram,$scope.trackedEntityTypes.selected, $scope.selectedOrgUnit);
        }else{
            promise = SearchGroupService.tetScopeSearch(searchGroup,$scope.trackedEntityTypes.selected, $scope.selectedOrgUnit);

        }

        return promise.then(function(res){
            var matches = [];
            if(res.status === "NOMATCH"){
                return;
            }
            if(res.status === "MATCHES" && $scope.registrationMode === "REGISTRATION"){
                matches = res.data;
            }
            return matches;
        });

    }

    $scope.showMatchesModal = function(allowRegistration, matches, onRefetch){
        var modalData = {
            allowRegistration: allowRegistration,
            translateWithTETName: $scope.translateWithTETName,
            optionSets: $scope.optionSets
        }

        return $modal.open({
                templateUrl: 'components/registration/matches-modal.html',
                controller: function($scope, $modalInstance, TEIGridService, orgUnit, data, modalData, refetchDataFn)
                {
                    $scope.allowRegistration = modalData.allowRegistration;
                    $scope.translateWithTETName = modalData.translateWithTETName;
                    $scope.gridData = TEIGridService.format(orgUnit.id, data, false, modalData.optionSets, null);
                    $scope.pager = {
                        ...(data && data.metaData && data.metaData.pager),
                        skipTotalPages: true
                    };
                    $scope.openTei = function(tei){
                        $modalInstance.close({ action: "OPENTEI", tei: tei});
                    }
                    $scope.register = function(destination){
                        $modalInstance.close({ action: "REGISTERTEI", destination: destination});
                    }
                    $scope.cancel = function(){
                        $modalInstance.close({ action: "CANCEL"});
                    }
                    $scope.refetchData = function(pager, sortColumn){
                        $scope.error = false;
                        $scope.tooManySearchResults = false;
                        refetchDataFn(pager, sortColumn)
                            .then(function(response){
                                if(response && response.rows && response.rows.length > 0){
                                    $scope.gridData = TEIGridService.format(orgUnit.id, response, false, modalData.optionSets, null);
                                }
                                else {
                                    $scope.gridData = [];
                                }
                            })
                            .catch(function(error){
                                $scope.gridData = null;
                                if(error && error.data && error.data.message === "maxteicountreached"){
                                    $scope.tooManySearchResults = true;
                                } else {
                                    $scope.error = true;
                                    console.log(error);
                                }
                            });
                    }
                },
                resolve: {
                    orgUnit: function(){
                        return $scope.selectedOrgUnit;
                    },
                    data: function(){
                        return matches;
                    },
                    refetchDataFn: function(){
                        return onRefetch;
                    },
                    modalData: function(){
                        return modalData;
                    }
                }
            }).result.then(function(res){
                if(res.action === "OPENTEI"){
                    openTei(res.tei);
                }else if(res.action === "REGISTERTEI"){
                    $scope.registerEntity(res.destination, true);
                }
            });
        
    }

    $scope.getMatchingTeisLength = function(){
        if($scope.matchingTeis){
            if($scope.matchingTeis.metaData && $scope.matchingTeis.metaData.pager && $scope.matchingTeis.metaData.pager.total){
                return $scope.matchingTeis.metaData.pager.total;
            }else if($scope.matchingTeis && $scope.matchingTeis.rows){
                return $scope.matchingTeis.rows.length;
            }
        }
        return 0;
    }

    var showDuplicateModal = function(duplicateTei, field){
        var modalData = {
            orgUnit: $scope.selectedOrgUnit,
            data: duplicateTei,
            attribute: field,
            optionSets: $scope.optionSets,
            translateWithTEAName: $scope.translateWithTEAName,
            translateWithTETName: $scope.translateWithTETName
        };

        return $modal.open({
            templateUrl: 'components/registration/duplicate-modal.html',
            controller: function($scope,$modalInstance, TEIGridService,modalData)
            {
                $scope.attribute = modalData.attribute;
                $scope.gridData = TEIGridService.format(modalData.orgUnit.id, modalData.data, false, modalData.optionSets, null);
                $scope.translateWithTEAName = modalData.translateWithTEAName;
                $scope.translateWithTETName = modalData.translateWithTETName;
                $scope.openTei = function(tei){
                    $modalInstance.close({ action: "OPENTEI", tei: tei});
                }
                $scope.cancel = function(){
                    $modalInstance.close({ action: "CANCEL"});
                }
            },
            resolve: {
                modalData: function(){
                    return modalData;
                }
            }
        }).result.then(function(res){
            var def = $q.defer();
            if(res.action === "OPENTEI"){
                def.resolve();
                openTei(res.tei);
                return def.promise;
            }else{
                def.reject();
                return def.promise;
            }
        });
    }

    var openTei = function(tei){
        $location.path('/dashboard').search({tei: tei.id,
            program: $scope.selectedProgram ? $scope.selectedProgram.id: null,
            ou: $scope.selectedOrgUnit.id});
    }

    $scope.showAttributeMap = function (obj, id) {
        var lat = "",
            lng = "";
        if (obj[id] && obj[id].length > 0) {
            var coordinates = obj[id].split(",");
            lng = coordinates[0];
            lat = coordinates[1];
        }
        var modalInstance = $modal.open({
            templateUrl: '../dhis-web-commons/angular-forms/map.html',
            controller: 'MapController',
            windowClass: 'modal-full-window',
            resolve: {
                location: function () {
                    return {lat: lat, lng: lng};
                }
            }
        });

        modalInstance.result.then(function (location) {
            if (angular.isObject(location)) {
                obj[id] = location.lng + ',' + location.lat;
            }
        }, function () {
        });
    };

    $scope.showDataElementMap = function (obj, id) {
        var lat = "",
            lng = "";
        if (obj[id] && obj[id].length > 0) {
            var coordinates = obj[id].split(",");
            lng = coordinates[0];
            lat = coordinates[1];
        }
        var modalInstance = $modal.open({
            templateUrl: '../dhis-web-commons/angular-forms/map.html',
            controller: 'MapController',
            windowClass: 'modal-full-window',
            resolve: {
                location: function () {
                    return {lat: lat, lng: lng};
                }
            }
        });

        modalInstance.result.then(function (location) {
            if (angular.isObject(location)) {
                obj[id] = location.lng + ',' + location.lat;
            }
        }, function () {
        });
    };

    $scope.showProgramStageMap = function(event){
        var modalInstance = $modal.open({
            templateUrl: '../dhis-web-commons/angular-forms/map.html',
            controller: 'MapController',
            windowClass: 'modal-full-window',
            resolve: {
                location: function () {
                    return {lat: event.coordinate.latitude, lng: event.coordinate.longitude};
                }
            }
        });

        modalInstance.result.then(function (location) {
            if(angular.isObject(location)){
                event.coordinate.latitude = location.lat;
                event.coordinate.longitude = location.lng;
            }
        }, function () {
        });
    };

    $scope.saveDatavalue = function () {
        $scope.currentEventOriginal = angular.copy($scope.currentEvent);
        $scope.executeRules();
    };

    $scope.saveEventDate = function(){
        $scope.saveDatavalue();
    }

    $scope.saveAssignedUser = function () {
        $scope.saveDatavalue();
    };

    $scope.verifyEventExpiryDate = function(field) {
        if(!$scope.userAuthority.canEditExpiredStuff){
            var date = $scope.currentEvent[field];
            if(!date) {
                var modalOptions = {
                    headerText: 'warning',
                    bodyText: 'no_blank_date'
                };
                $scope.currentEvent[field] = $scope.currentEventOriginal[field];
                ModalService.showModal({}, modalOptions);
                return;
            }
    
            if (!DateUtils.verifyExpiryDate(date, $scope.selectedProgram.expiryPeriodType, $scope.selectedProgram.expiryDays, true)) {
                $scope.currentEvent[field] = $scope.currentEventOriginal[field];
                return;
            }
        }

    };

    var isInSearchOrgUnits = function(orgUnitPath, searchOrgUnits){
        if($scope.userAuthority.ALL) return true;
        if(!orgUnitPath) return false;
        return TCOrgUnitService.isPathInOrgUnitList(orgUnitPath, searchOrgUnits);
    }

    $scope.reportDateEditable = function() {
        //Check if user has data write to current program stage
        if(!$scope.currentStage || !$scope.currentStage.access.data.write) return false;
        //Check if organisation unit is closed
        if($scope.selectedOrgUnit.closedStatus) return false;
        //Check if event is the selected org unit or event is scheduled and org unit exists in users search org units
        if($scope.currentEvent.orgUnit !== $scope.selectedOrgUnit.id && !($scope.currentEvent.status==='SCHEDULE' && isInSearchOrgUnits($scope.currentEvent.orgUnitPath, userSearchOrgUnits))) return false;
        // Check if currentProgramStage blocks entry form when status is completed
        if($scope.currentStage && $scope.currentStage.blockEntryForm && $scope.currentEvent.status ==='COMPLETED') return false;
        //Check if tei is inactive
        if($scope.selectedTei.inactive) return false;     
        //Check if event is expired and user can edit expired stuff
        if(($scope.currentEvent.expired && !$scope.userAuthority.canEditExpiredStuff)) return false;

        return true;
    }

    $scope.translateWithTETName = function(text, nameToLower){
        var trackedEntityTypeName = $scope.selectedProgram ? 
            $scope.selectedProgram.trackedEntityType.displayName : 
            ($scope.trackedEntityTypes.selected ? $scope.trackedEntityTypes.selected.displayName : "tracked entity instance");

        if(nameToLower) trackedEntityTypeName = trackedEntityTypeName.toLowerCase();
        var translated = $translate.instant(text);

        return translated.replace("{trackedEntityTypeName}", trackedEntityTypeName);
    }

    $scope.translateWithMatchingTeisLength = function(multipleText, singleText){
        var length = 0;
        if($scope.matchingTeisCount){
            length = $scope.matchingTeisCount;
        }
        if(length === 1){
            return $translate.instant(singleText);
        } 
        var translated = $translate.instant(multipleText);
        return translated.replace("{count}", length.toString());
    }

    $scope.translateWithTEAName = function(text,attributeId, toLower){
        var attributeName = "attribute";
        var attribute = $scope.attributesById[attributeId];
        if(attribute) attributeName = attribute.displayName;
        if(toLower) attributeName = attributeName.toLowerCase();
        var translated = $translate.instant(text);
        return translated.replace("{trackedEntityAttributeName}", attributeName);
    }

    $scope.attributeFieldDisabled = function(attribute){
        if($scope.isDisabled(attribute)) return true;
        if(!$scope.teTypeAttributesById || !$scope.teTypeAttributesById[attribute.id]){
            if($scope.selectedTei && $scope.selectedTei.programOwnersById && $scope.selectedProgram && $scope.selectedTei.programOwnersById[$scope.selectedProgram.id] && $scope.selectedTei.programOwnersById[$scope.selectedProgram.id] != $scope.selectedOrgUnit.id) return true;
            if($scope.selectedOrgUnit.closedStatus) return true;
        }
        if(!$scope.hasTeiWrite()) return true;
        return false;
    }

    $scope.saveAttributedDisabledButton = function(){
        if(!$scope.hasTeiWrite()) return true;
        return false;
    }
    

    $scope.dataElementEditable = function(prStDe){
        if($scope.eventEditable()){
            if($scope.assignedFields && $scope.assignedFields[$scope.currentEvent.event] && $scope.assignedFields[$scope.currentEvent.event][prStDe.dataElement.id]){
                return false;
            } 
            return true;
        }
        return false;
    }

    $scope.eventEditable = function(){
        if($scope.selectedProgram && $scope.selectedTei && $scope.selectedTei.programOwnersById && $scope.selectedTei.programOwnersById[$scope.selectedProgram.id] != $scope.selectedOrgUnit.id) return false;
        if($scope.selectedOrgUnit.closedStatus || $scope.selectedEnrollment.status !== 'ACTIVE' || $scope.currentEvent.editingNotAllowed) return false;
        if($scope.currentEvent.expired && !$scope.userAuthority.canEditExpiredStuff) return false;
        return true;
    }

    $scope.deleteFile = function(tei, attribute){
        
        if( !attribute ){
            NotificationService.showNotifcationDialog($translate.instant("error"), $translate.instant("missing_file_identifier"));
            return;
        }
        
        var modalOptions = {
            closeButtonText: 'cancel',
            actionButtonText: 'remove',
            headerText: 'remove',
            bodyText: 'are_you_sure_to_remove'
        };

        ModalService.showModal({}, modalOptions).then(function(result){            
            $scope.fileNames[attribute] = "";
            $scope.fileNames["undefined"][attribute] = "";
            tei[attribute] = "";
        });
    };

    $scope.downloadFile = function(tei, attributeId) {      
        if( !tei || !tei.trackedEntityInstance || !attributeId){
            NotificationService.showNotifcationDialog($translate.instant("error"), $translate.instant("missing_file_identifier"));
            return;
        }
        
        $window.open('../api/trackedEntityInstances/' + tei.trackedEntityInstance + '/' + attributeId + '/image', '_blank', '');
    };

    $scope.setDateOnFocus = function(currentValue, date) {
        if(!currentValue) {
            if( date ) {
                $scope.currentEvent.eventDate = date;
            } else {
                $scope.currentEvent.eventDate = DateUtils.getToday();
            }
        }
    };

    $scope.setTrackedEntityType = function(){
        $scope.getAttributes($scope.registrationMode);
        setSearchConfig();
    }

    $scope.showRegistrationButtons = function(){
        return $scope.registrationMode === 'REGISTRATION' && ($scope.selectedProgram || showTetRegistrationButtons());
    }

    $scope.showTetRegistrationWarning =  function(){
        return $scope.registrationMode === 'REGISTRATION' && (!$scope.selectedProgram && $scope.trackedEntityTypes.selected && !showTetRegistrationButtons());
    }

    $scope.attributeIsRequired = function(attributeId, attributeMandatory) {
        //If has authority Ignore required validation, skip required
        if($scope.userAuthority.ignoreRequiredTrackerValueValidation) {
            return false;
        }
        return attributeMandatory || $scope.mandatoryFields[attributeId];
    }

    var showTetRegistrationButtons = function(){
        return $scope.trackedEntityTypes.selected && $scope.attributes && $scope.attributes.length > 3;
    }
});